Skip to content

fix(webhooks): handle svix 2.0.0 Webhook.verify() returning None - #196

Draft
Sbussiso wants to merge 1 commit into
masterfrom
ci-fix/32700481827
Draft

fix(webhooks): handle svix 2.0.0 Webhook.verify() returning None#196
Sbussiso wants to merge 1 commit into
masterfrom
ci-fix/32700481827

Conversation

@Sbussiso

Copy link
Copy Markdown
Contributor

Root cause

The Weekly dependency refresh workflow (run #32700481827) runs uv lock --upgrade before the test gate. That resolved svix>=1.99.1svix 2.0.0, a breaking major release.

svix 2.0.0 changed Webhook.verify() to return None — it now only validates the signature; the parsed event dict is no longer returned (signature changed from -> dict to -> None). Both webhook handlers did event = wh.verify(payload, headers) then event.get("type"), so 39 tests crashed with:

AttributeError: 'NoneType' object has no attribute 'get'
app/api/webhooks.py:102: event_type = event.get("type")

Affected: all of test_resend_webhook.py, test_webhooks.py, and test_welcome_email.py (both the Clerk /api/webhooks/clerk and Resend /api/webhooks/resend routes).

Fix

Keep wh.verify() as the signature-validation call (it still raises WebhookVerificationError on a bad signature in both svix 1.x and 2.x), then parse the now-authentic payload with json.loads() ourselves. This is version-agnostic:

  • svix 1.99.1verify() returns the dict; we overwrite it with the same dict (no-op).
  • svix 2.0.0verify() returns None; we parse the verified bytes.

verify() succeeding is proof the payload is authentic, so decoding it ourselves is safe and equivalent to what the library used to do internally.

Verification

Reproduced the CI failure locally (installed svix 2.0.0 via uv lock --upgrade), then confirmed the fix:

  • ✅ Full backend suite: 699 passed, 0 failed under svix 2.0.0 (includes all 39 previously-failing webhook tests)
  • ruff check clean
  • ✅ The 3 previously-failing test files pass standalone: 43 passed

This also lets the weekly refresh PR go green again — without this fix, every weekly refresh that pulls svix 2.0.0 will stay red.

CI run

https://github.com/SourceBox-LLC/Sentinel-Command/actions/runs/32700481827

svix 2.0.0 is a breaking major release: Webhook.verify() now returns
None (it only validates the signature; the parsed event is no longer
returned). The weekly dependency refresh workflow runs 'uv lock
--upgrade', which resolves svix>=1.99.1 to 2.0.0, and 39 webhook
tests crashed with AttributeError: 'NoneType' object has no
attribute 'get' at event.get('type') in both the Clerk and Resend
handlers.

Keep wh.verify() as the signature-validation call (it still raises
WebhookVerificationError on a bad signature in both 1.x and 2.x),
then parse the now-authentic payload with json.loads() ourselves.
This is version-agnostic: identical behavior under svix 1.99.1
(verify returns the dict, which we overwrite with the same dict)
and 2.0.0 (verify returns None, we parse the verified bytes).

Verified: full backend suite (699 tests) passes under svix 2.0.0,
including all 39 previously-failing webhook tests. ruff clean.

CI run: https://github.com/SourceBox-LLC/Sentinel-Command/actions/runs/32700481827
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant